package com.ruoyi.labsafety.service.impl;

import java.util.Date;
import java.util.List;

import org.quartz.SchedulerException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.support.CronSequenceGenerator;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.ruoyi.common.core.text.Convert;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.labdata.domain.LabFile;
import com.ruoyi.labdata.domain.LabFlowInstance;
import com.ruoyi.labdata.service.ILabFileService;
import com.ruoyi.labdata.service.ILabFlowInstanceService;
import com.ruoyi.labsafety.domain.LabSafetyCheckForm;
import com.ruoyi.labsafety.domain.LabSafetyCheckIndex;
import com.ruoyi.labsafety.domain.LabSafetyCheckRelUser;
import com.ruoyi.labsafety.domain.LabSafetyCheckTargetOrg;
import com.ruoyi.labsafety.domain.LabSafetyCheckTask;
import com.ruoyi.labsafety.mapper.LabSafetyCheckFormMapper;
import com.ruoyi.labsafety.service.ILabSafetyCheckFormService;
import com.ruoyi.labsafety.service.ILabSafetyCheckIndexItemService;
import com.ruoyi.labsafety.service.ILabSafetyCheckIndexService;
import com.ruoyi.labsafety.service.ILabSafetyCheckRelFileService;
import com.ruoyi.labsafety.service.ILabSafetyCheckRelIndexItemService;
import com.ruoyi.labsafety.service.ILabSafetyCheckRelUserService;
import com.ruoyi.labsafety.service.ILabSafetyCheckTargetOrgService;
import com.ruoyi.labsafety.service.ILabSafetyCheckTaskService;
import com.ruoyi.quartz.domain.SysJob;
import com.ruoyi.quartz.service.ISysJobService;
import com.ruoyi.system.utils.FileTypeEnum;

/**
 * 安全检查单Service业务层处理
 * 
 * @author winner pan
 * @date 2022-03-27
 */
@Service("safetyCheck")
public class LabSafetyCheckFormServiceImpl implements ILabSafetyCheckFormService {
	private static final String belongType = FileTypeEnum.checkForm.getValue();
	@Autowired
	private ILabFileService labFileService;
	@Autowired
	private LabSafetyCheckFormMapper labSafetyCheckFormMapper;

	@Autowired
	private ILabFlowInstanceService labFlowInstanceService;

	@Autowired
	private ILabSafetyCheckRelUserService safetyCheckRelUserService;

	@Autowired
	private ILabSafetyCheckTargetOrgService safetyCheckTargetOrgService;

	@Autowired
	private ILabSafetyCheckRelFileService safetyCheckRelFileService;

	@Autowired
	private ILabSafetyCheckRelIndexItemService safetyCheckRelIndexItemService;

	@Autowired
	private ILabSafetyCheckIndexItemService safetyCheckIndexItemService;

	@Autowired
	private ILabSafetyCheckIndexService safetyCheckIndexService;

	@Autowired
	private ILabSafetyCheckTaskService safetyCheckTaskService;

	@Autowired
	private ISysJobService jobService;

	/**
	 * 查询安全检查单
	 * 
	 * @param instanceId
	 *            安全检查单ID
	 * @return 安全检查单
	 */
	@Override
	public LabSafetyCheckForm selectLabSafetyCheckFormById(Long instanceId) {
		LabSafetyCheckForm labSafetyCheckForm = labSafetyCheckFormMapper.selectLabSafetyCheckFormById(instanceId);
		LabFlowInstance labFlowInstance = labFlowInstanceService.selectLabFlowInstanceById(instanceId);
		labSafetyCheckForm.setFlowName(labFlowInstance.getFlowName());
		labSafetyCheckForm.setCopyToUsers(labFlowInstance.getCopyToUsers());
		labSafetyCheckForm.setFlowStatusOpt(labFlowInstance.getFlowStatusOpt());

		String safetyTemplateOpt = labSafetyCheckForm.getSafetyTemplateOpt();
		String[] safetyTemplateOptArray = Convert.toStrArray(safetyTemplateOpt);
		labSafetyCheckForm.setSafetyTemplateOptArray(safetyTemplateOptArray);
		Long[] indexIds = Convert.toLongArray(safetyTemplateOpt);
		List<LabSafetyCheckIndex> labSafetyCheckIndexList = safetyCheckIndexService
				.selectLabSafetyCheckIndexByIds(indexIds);
		labSafetyCheckForm.setLabSafetyCheckIndexList(labSafetyCheckIndexList);

		// 检查人员
		LabSafetyCheckRelUser checkRelUser = new LabSafetyCheckRelUser();
		checkRelUser.setInstanceId(instanceId);
		List<LabSafetyCheckRelUser> labSafetyCheckRelUsers = safetyCheckRelUserService
				.selectLabSafetyCheckRelUserList(checkRelUser);
		StringBuffer checkUserSB = new StringBuffer();
		for (LabSafetyCheckRelUser labSafetyCheckRelUser : labSafetyCheckRelUsers) {
			checkUserSB.append(labSafetyCheckRelUser.getUserId());
			checkUserSB.append(",");
		}
		labSafetyCheckForm.setCheckUsers(checkUserSB.toString());

		LabSafetyCheckTargetOrg checkTargetOrg = new LabSafetyCheckTargetOrg();
		checkTargetOrg.setInstanceId(instanceId);
		List<LabSafetyCheckTargetOrg> labSafetyCheckTargetOrgs = safetyCheckTargetOrgService
				.selectLabSafetyCheckTargetOrgList(checkTargetOrg);
		StringBuffer checkOrgSB = new StringBuffer();
		for (LabSafetyCheckTargetOrg labSafetyCheckTargetOrg : labSafetyCheckTargetOrgs) {
			checkOrgSB.append(labSafetyCheckTargetOrg.getOrgId());
			checkOrgSB.append(",");
		}
		labSafetyCheckForm.setCheckTargetOrgs(checkOrgSB.toString());
		
		List<LabFile> labFiles = labFileService.getFiles(instanceId, belongType);
		labSafetyCheckForm.setFiles(labFiles);

		return labSafetyCheckForm;
	}

	/**
	 * 查询安全检查单列表
	 * 
	 * @param labSafetyCheckForm
	 *            安全检查单
	 * @return 安全检查单
	 */
	@Override
	public List<LabSafetyCheckForm> selectLabSafetyCheckFormList(LabSafetyCheckForm labSafetyCheckForm) {
		return labSafetyCheckFormMapper.selectLabSafetyCheckFormList(labSafetyCheckForm);
	}

	/**
	 * 新增安全检查单
	 * 
	 * @param labSafetyCheckForm
	 *            安全检查单
	 * @return 结果
	 */
	@Override
	@Transactional
	public int insertLabSafetyCheckForm(LabSafetyCheckForm labSafetyCheckForm) {
		labSafetyCheckForm.setCountNum(0);
		labSafetyCheckForm.setCreateBy(SecurityUtils.getUsername());
		//labSafetyCheckForm.setCreateTime(DateUtils.getNowDate());
		labSafetyCheckForm.setCreateOrgId(SecurityUtils.getLoginUser().getUser().getDeptId());
		labSafetyCheckForm.setFlowName(labSafetyCheckForm.getTaskName());
		String cron = labSafetyCheckForm.getCheckFrequencyOpt();
		if (cron != null && cron.indexOf("|") > 0) {
			cron = cron.substring(0, cron.indexOf("|"));
		}
		if (cron != null && !cron.equals("1") && !CronSequenceGenerator.isValidExpression(cron)) {
			throw new RuntimeException("定时执行表达式不正确，表达式:" + cron);
		}
		labFlowInstanceService.insertLabFlowInstance(labSafetyCheckForm);
		if (!labSafetyCheckForm.getSafetyCheckOpt().equals("3")) {
			this.insertCheckUsers(labSafetyCheckForm);
			this.insertCheckTargetOrgs(labSafetyCheckForm);
		}

		this.insertCheckFiles(labSafetyCheckForm);

		this.insertCheckIndexItem(labSafetyCheckForm);

		return labSafetyCheckFormMapper.insertLabSafetyCheckForm(labSafetyCheckForm);
	}

	private void insertCheckIndexItem(LabSafetyCheckForm labSafetyCheckForm) {

		Long instanceId = labSafetyCheckForm.getInstanceId();
		safetyCheckRelIndexItemService.deleteLabSafetyCheckRelIndexItemByInstanceId(instanceId);

		Long[] indexIds = Convert.toLongArray(labSafetyCheckForm.getSafetyTemplateOpt());
		safetyCheckRelIndexItemService.insertLabSafetyCheckRelIndexItemByIndexId(instanceId, indexIds);

	}

	// 插入附件
	private void insertCheckFiles(LabSafetyCheckForm labSafetyCheckForm) {
		// safetyCheckRelFileService.deleteLabSafetyCheckRelFileByInstanceId(labSafetyCheckForm.getInstanceId());
		labFileService.updateFiles(labSafetyCheckForm.getFiles(), labSafetyCheckForm.getInstanceId(), belongType);
	}

	// 插入检查目标
	private void insertCheckTargetOrgs(LabSafetyCheckForm labSafetyCheckForm) {

		safetyCheckTargetOrgService.deleteLabSafetyCheckTargetOrgByInstanceId(labSafetyCheckForm.getInstanceId());

		String checkTargetOrgs = labSafetyCheckForm.getCheckTargetOrgs();
		String[] checkTargetOrgsArray = Convert.toStrArray(checkTargetOrgs);
		for (String orgId : checkTargetOrgsArray) {
			LabSafetyCheckTargetOrg checkTargetOrg = new LabSafetyCheckTargetOrg();
			checkTargetOrg.setOrgId(Long.valueOf(orgId));
			checkTargetOrg.setInstanceId(labSafetyCheckForm.getInstanceId());
			safetyCheckTargetOrgService.insertLabSafetyCheckTargetOrg(checkTargetOrg);
		}
	}

	// 插入检查人员
	private void insertCheckUsers(LabSafetyCheckForm labSafetyCheckForm) {

		safetyCheckRelUserService.deleteLabSafetyCheckRelUserByInstanceId(labSafetyCheckForm.getInstanceId());

		String checkUsers = labSafetyCheckForm.getCheckUsers();
		String[] checkUsersArray = Convert.toStrArray(checkUsers);
		for (String userId : checkUsersArray) {
			LabSafetyCheckRelUser checkRelUser = new LabSafetyCheckRelUser();
			checkRelUser.setUserId(Long.valueOf(userId));
			checkRelUser.setInstanceId(labSafetyCheckForm.getInstanceId());
			safetyCheckRelUserService.insertLabSafetyCheckRelUser(checkRelUser);
		}
	}

	/**
	 * 修改安全检查单
	 * 
	 * @param labSafetyCheckForm
	 *            安全检查单
	 * @return 结果
	 */
	@Override
	@Transactional
	public int updateLabSafetyCheckForm(LabSafetyCheckForm labSafetyCheckForm) {
		labSafetyCheckForm.setCountNum(0);
		labSafetyCheckForm.setFlowName(labSafetyCheckForm.getTaskName());
		String cron = labSafetyCheckForm.getCheckFrequencyOpt();
		if (cron != null && cron.indexOf("|") > 0) {
			cron = cron.substring(0, cron.indexOf("|"));
		}
		if (cron != null && !cron.equals("1") && !CronSequenceGenerator.isValidExpression(cron)) {
			throw new RuntimeException("定时执行表达式不正确，表达式:" + cron);
		}
		labFlowInstanceService.updateLabFlowInstance(labSafetyCheckForm);
		if (!labSafetyCheckForm.getSafetyCheckOpt().equals("3")) {
			this.insertCheckUsers(labSafetyCheckForm);
			this.insertCheckTargetOrgs(labSafetyCheckForm);
		}
		this.insertCheckFiles(labSafetyCheckForm);

		this.insertCheckIndexItem(labSafetyCheckForm);

		return labSafetyCheckFormMapper.updateLabSafetyCheckForm(labSafetyCheckForm);
	}

	/**
	 * 批量删除安全检查单
	 * 
	 * @param instanceIds
	 *            需要删除的安全检查单ID
	 * @return 结果
	 */
	@Override
	@Transactional
	public int deleteLabSafetyCheckFormByIds(Long[] instanceIds) {
		for(Long id : instanceIds){
			labFileService.deleteLabFile(id, belongType);
		}
		labSafetyCheckFormMapper.deleteLabSafetyCheckFormByIds(instanceIds);
		return instanceIds.length;
	}

	/**
	 * 删除安全检查单信息
	 * 
	 * @param instanceId
	 *            安全检查单ID
	 * @return 结果
	 */
	@Override
	public int deleteLabSafetyCheckFormById(Long instanceId) {
		labFileService.deleteLabFile(instanceId, belongType);
		this.safetyCheckRelFileService.deleteLabSafetyCheckRelFileByInstanceId(instanceId);
		this.safetyCheckRelIndexItemService.deleteLabSafetyCheckRelIndexItemByInstanceId(instanceId);
		this.safetyCheckTargetOrgService.deleteLabSafetyCheckTargetOrgByInstanceId(instanceId);
		this.safetyCheckRelUserService.deleteLabSafetyCheckRelUserByInstanceId(instanceId);

		return labSafetyCheckFormMapper.deleteLabSafetyCheckFormById(instanceId);
	}

	@Override
	public int submitLabSafetyCheckForm(LabSafetyCheckForm labSafetyCheckForm) {
		this.updateLabSafetyCheckForm(labSafetyCheckForm);
		// this.updateApproval(labSafetyCheckForm.getInstanceId()); // TODO
		return labFlowInstanceService.commitFlow(labSafetyCheckForm);
	}

	@Override
	public void updateApproval(Long instanceId) {
		labSafetyCheckFormMapper.updateApproval(instanceId);
		LabSafetyCheckForm labSafetyCheckForm = labSafetyCheckFormMapper.selectLabSafetyCheckFormById(instanceId);//
		if (labSafetyCheckForm.getSafetyCheckOpt().equals("3")) {
			// 督导巡查的不生成任务
			return;
		}
		if(labSafetyCheckForm.getFlowStatusOpt().equals("finished")){
			// 判断是单次检查还是重复检查
			if (labSafetyCheckForm.getTaskCycleOpt().equals("2")) {
				saveTaskJobInfo(labSafetyCheckForm);
			} else {
				generalTask(labSafetyCheckForm);
			}
		}
	}

	public void generalTask(LabSafetyCheckForm labSafetyCheckForm) {
		labSafetyCheckForm.setCountNum(0);
		this.labSafetyCheckFormMapper.updateLabSafetyCheckForm(labSafetyCheckForm);
		LabSafetyCheckTargetOrg checkTargetOrg = new LabSafetyCheckTargetOrg();
		checkTargetOrg.setInstanceId(labSafetyCheckForm.getInstanceId());
		List<LabSafetyCheckTargetOrg> labSafetyCheckTargetOrgs = safetyCheckTargetOrgService
				.selectLabSafetyCheckTargetOrgList(checkTargetOrg);

		for (LabSafetyCheckTargetOrg labSafetyCheckTargetOrg : labSafetyCheckTargetOrgs) {

			LabSafetyCheckTask labSafetyCheckTask = new LabSafetyCheckTask();
			BeanUtils.copyProperties(labSafetyCheckForm, labSafetyCheckTask);
			// labSafetyCheckTask.setFlowName(null);
			labSafetyCheckTask.setCreateTime(null);
			labSafetyCheckTask.setInstanceId(null);
			labSafetyCheckTask.setStatus(null);
			labSafetyCheckTask.setCheckFormId(labSafetyCheckForm.getInstanceId());
			labSafetyCheckTask.setFlowStatusOpt(null);
			labSafetyCheckTask.setOrgId(labSafetyCheckTargetOrg.getOrgId());
			labSafetyCheckTask.setType(1); // 检查任务

			safetyCheckTaskService.insertLabSafetyCheckTask(labSafetyCheckTask);
		}
	}

	// 定时任务执行
	public void generalTaskJob(Integer instanceId) {
		// 读取定时任务，定时任务中需要保存有对应的任务ID值。
		LabSafetyCheckForm labSafetyCheckForm = labSafetyCheckFormMapper.selectLabSafetyCheckFormById(Long.valueOf(instanceId));
		String cron = labSafetyCheckForm.getCheckFrequencyOpt();
		if (cron != null && cron.indexOf("|") > 0) {
			cron = cron.substring(0, cron.indexOf("|"));
			Integer countNum = Integer.valueOf(cron.substring(cron.indexOf("|") + 1));
			if (labSafetyCheckForm.getCountNum() == null) {
				labSafetyCheckForm.setCountNum(0);
			}
			if (labSafetyCheckForm.getCountNum() + 1 < countNum) {
				checkJobDate(labSafetyCheckForm, cron);
				labSafetyCheckForm.setCountNum(labSafetyCheckForm.getCountNum() + 1);
				this.labSafetyCheckFormMapper.updateLabSafetyCheckForm(labSafetyCheckForm);
				return;
			}
		}
		checkJobDate(labSafetyCheckForm, cron);
		generalTask(labSafetyCheckForm);

	}

	private void checkJobDate(LabSafetyCheckForm labSafetyCheckForm, String cron) {
		// 判断定时任务的时间关系，如果下一个时间点晚于当前时间点，则关闭该定时任务。
		CronSequenceGenerator cronSequenceGenerator = new CronSequenceGenerator(cron);
		Date currentTime = new Date();
		Date nextTimePoint = cronSequenceGenerator.next(currentTime); // currentTime为计算下次时间点的开始时间
		Date nextNextTimePoint = cronSequenceGenerator.next(nextTimePoint);
		if (nextNextTimePoint.before(labSafetyCheckForm.getEndDate())) {
			SysJob sysJob = jobService.selectJobById(labSafetyCheckForm.getJobId());
			try {
				jobService.changeStatus(sysJob);
			} catch (SchedulerException e) {
				e.printStackTrace();
			}
		}
	}

	public void saveTaskJobInfo(LabSafetyCheckForm labSafetyCheckForm) {
		SysJob sysJob = new SysJob();
		sysJob.setJobName(labSafetyCheckForm.getFlowName());
		sysJob.setJobGroup("SYSTEM");
		String cron = labSafetyCheckForm.getCheckFrequencyOpt();
		if (cron.indexOf("|") > 0) {
			cron = cron.substring(0, cron.indexOf("|"));
		}
		sysJob.setCronExpression(cron);
		sysJob.setInvokeTarget("safetyCheck.generalTaskJob(" + labSafetyCheckForm.getInstanceId() + ")");
		sysJob.setStatus("1");
		sysJob.setCreateBy(labSafetyCheckForm.getCreateBy());
		sysJob.setCreateTime(labSafetyCheckForm.getCreateTime());
		try {
			jobService.insertJob(sysJob);
			labSafetyCheckForm.setJobId(sysJob.getJobId());
			this.labSafetyCheckFormMapper.updateLabSafetyCheckForm(labSafetyCheckForm);
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		}
	}

	public List<LabSafetyCheckForm> selectImmediatelyCheckForm() {
		return labSafetyCheckFormMapper.selectImmediatelyCheckForm();
	}

}
